/** ****************************************************************************
@addtogroup Calendar
@{
*******************************************************************************/

#include <stdio.h>
#include "utils.h"
#include "unios.h"
#include "calendar.h"

// 前一天晚上0点
const unios_time_t nzero = {24, 0, 0};
// 第二天早上0点
const unios_time_t ezero = {0, 0, 0};
/// 时间折算起始点(_secondsCount==0 时表示的实际时间)
const unios_date_t dateBase = {1970, 1, 1};
/// 星期计算起始日期(_secondsCount==0 时表示的是星期几)
const uint8_t whatDayBase = 4;
/// 非闰年每个月有多少天
const static uint8_t days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int timeCompare(uint8_t hour1, uint8_t minute1, uint8_t second1, uint8_t hour2, uint8_t minute2, uint8_t second2) {
	if(hour1 > hour2) {
		return 1;
	} else if(hour1 < hour2) {
		return -1;
	} else {
		if(minute1 > minute2) {
			return 1;
		} else if(minute1 < minute2) {
			return -1;
		} else {
			if(second1 > second2) {
				return 1;
			} else if(second1 < second2) {
				return -1;
			} else {
				return 0;
			}
		}
	}
}

int timeCompare2(const unios_time_t* t1, const unios_time_t* t2) {
	return timeCompare(t1->hour, t1->minute, t1->second, t2->hour, t2->minute, t2->second);
}

bool timeBetween(const unios_time_t* t, const unios_time_t* start, const unios_time_t* end) {
	if(timeCompare2(start, end) <= 0) {
		return ( (timeCompare2(t, start) >= 0) && (timeCompare2(t, end) <= 0) );
	} else {
		return ( timeBetween(t, start, &nzero) || timeBetween(t, &ezero, end) );
	}
}

bool isLeapYear(uint16_t year) {
    return (year % 400 == 0 ) || (year % 4 == 0 && year % 100 != 0);
}

uint8_t daysInMonth(uint16_t year, uint8_t month) {
	if((month == 2) && isLeapYear(year)) { return 29; }
	return days[month-1];
}

uint16_t daysInYear(uint16_t year) {
	return isLeapYear(year) ? 366 : 365;
}

uint16_t date2Days(unios_date_t *date) {
	// 计算整天数
	uint16_t days = date->day - 1;
	for(int m=1; m<date->month; m++) {
		days += daysInMonth(date->year, m);
	}
	for(int y=dateBase.year; y<date->year; y++) {
		days += daysInYear(y);
	}

	return days;
}

unios_date_t days2Date(uint16_t days) {
	unios_date_t date;

	// 计算星期几
	date.weekday = (days + whatDayBase) % 7;
	
	// 计算年
	for(date.year = dateBase.year;
		days >= daysInYear(date.year);
		days -= daysInYear(date.year), date.year++);

	// 计算月
	for(date.month = dateBase.month;
		days >= daysInMonth(date.year, date.month);
		days -= daysInMonth(date.year, date.month), date.month++);

	// 计算日
	date.day = days + dateBase.day;

	return date;
}

uint32_t dateTime2Seconds(unios_datetime_t *dateTime) {
	// 计算时、分、秒
	uint32_t nsec = dateTime->time.second;
	nsec += dateTime->time.minute * 60L;
	nsec += dateTime->time.hour * (60L*60);

	// 计算整天
	nsec += date2Days(&dateTime->date) * (24L*60*60);

	return nsec;
}

unios_datetime_t seconds2DateTime(uint32_t seconds) {
	unios_datetime_t dt;

	// 计算时、分、秒
	dt.time.second = seconds % 60;
	dt.time.minute = (seconds / 60) % 60;
	dt.time.hour   = (seconds / (60*60)) % 24;

	// 计算日期
	dt.date = days2Date(seconds / (24L*60*60));

	return dt;
}

uint8_t date2Weekday(unios_date_t *date) {
	return (date2Days(date) + whatDayBase) % 7;
}

uint8_t whatDayIsToday() {
	return (unios_rtcsec_get() / (24L*60*60)  + whatDayBase) % 7;
}

const char* getDateTimeString(uint32_t timestamp) {
	static char str[20];	
	unios_datetime_t dt = seconds2DateTime(timestamp);
	sprintf(str, "%04d-%02d-%02d %02d:%02d:%02d", dt.date.year, dt.date.month, dt.date.day, dt.time.hour, dt.time.minute, dt.time.second);
	return str;
}

uint32_t hexdecTime2timestamp(void *bytes) {
	if(!bytes) { return 0; }
	unios_datetime_t datetime;
	uint8_t *data = (uint8_t*)bytes;
	datetime.date.year = hexdec2int(data[0])*100 + hexdec2int(data[1]);
	datetime.date.month = hexdec2int(data[2]);
	datetime.date.day = hexdec2int(data[3]);
	datetime.time.hour = hexdec2int(data[4]);
	datetime.time.minute = hexdec2int(data[5]);
	datetime.time.second = hexdec2int(data[6]);
	return dateTime2Seconds(&datetime);
}

void timestamp2hexdecTime(uint32_t timestamp, uint8_t *bytes) {
	if(!bytes) { return; }
	unios_datetime_t datetime = seconds2DateTime(timestamp);
	bytes[0] = int2hexdec(datetime.date.year / 100);
	bytes[1] = int2hexdec(datetime.date.year % 100);
	bytes[2] = int2hexdec(datetime.date.month);
	bytes[3] = int2hexdec(datetime.date.day);
	bytes[4] = int2hexdec(datetime.time.hour);
	bytes[5] = int2hexdec(datetime.time.minute);
	bytes[6] = int2hexdec(datetime.time.second);
}


/// @}
